#include <scene.h>
#include <button.h>
#include <scene_manager.h>
#include <iostream>
#include <tilemap.h>
#include <search/dfs.h>
#include <list_selecter.h>
#include <thread>
#include <win32_utils.h>
#include <iostream>
#include <cmath>
#include <optional>
#include <vector>
#include <algorithm>

class SceneRaycasting : public Scene {
private:
    Vector2 curser;
    std::vector<std::pair<Vector2, Vector2>> walls;  // 墙壁线段
    bool showRays = true;
    bool showIntersections = true;
    
public:
    SceneRaycasting() {
        // 初始化墙壁
        walls.push_back({{200, 300}, {260, 750}});
        walls.push_back({{1000, 300}, {1000, 500}});
        walls.push_back({{300, 200}, {600, 400}});
        walls.push_back({{1300, 300}, {1300, 750}});
        walls.push_back({{500, 489}, {234, 567}});
        
        // 添加一些边界墙
        walls.push_back({{0, 0}, {1600, 0}});
        walls.push_back({{0, 0}, {0, 900}});
        walls.push_back({{1600, 0}, {1600, 900}});
        walls.push_back({{0, 900}, {1600, 900}});
        
        // 添加一些随机墙
        for (int i = 0; i < 2; i++) {
            walls.push_back({
                {(float)(rand() % 1500 + 50), (float)(rand() % 800 + 50)},
                {(float)(rand() % 1500 + 50), (float)(rand() % 800 + 50)}
            });
        }
    }
    
    ~SceneRaycasting() {}

    void init() override {
        
    }

    void render(float dt) override {
        ClearBackground(BLACK);
        curser = GetMousePosition();
        
        // 绘制所有墙壁
        for (auto& wall : walls) {
            DrawLineV(wall.first, wall.second, WHITE);
        }
        
        // 生成射线方向（从鼠标位置向各个方向发射）
        std::vector<Vector2> rayDirections;
        // generateRayDirections(rayDirections, 360); // 360条射线
        rayDirections.clear();
        for(auto& wall : walls){
            rayDirections.push_back(wall.first);
            rayDirections.push_back(wall.second);
        }
            
        
        // 计算并绘制射线
        std::vector<Vector2> intersections;
        for (auto& rayDir : rayDirections) {
            auto closestIntersection = castRay(curser, rayDir);
            if (closestIntersection.has_value()) {
                intersections.push_back(closestIntersection.value());
                if (showRays) {
                    DrawLineV(curser, closestIntersection.value(), {255, 255, 0, 100}); // 半透明黄色射线
                }
            }
        }
        
        // 绘制交点
        if (showIntersections) {
            for (auto& intersection : intersections) {
                DrawCircleV(intersection, 3, RED);
            }
        }
        
        // 绘制视线多边形（填充视线区域）
        if (intersections.size() >= 3) {
            // 按角度排序交点，形成多边形
            std::vector<Vector2> sortedIntersections = sortPointsByAngle(intersections, curser);
            for (size_t i = 0; i < sortedIntersections.size(); i++) {
                size_t next = (i + 1) % sortedIntersections.size();
                DrawTriangle(curser, sortedIntersections[i], sortedIntersections[next], {255, 0, 0, 50});
            }
        }
        
        // 绘制UI信息
        DrawText("R/I", 10, 10, 20, GREEN);
        DrawText(TextFormat("curser: (%.0f, %.0f)", curser.x, curser.y), 10, 40, 20, GREEN);
        DrawText(TextFormat("rays: %d", (int)rayDirections.size()), 10, 70, 20, GREEN);
        DrawText(TextFormat("walls: %d", (int)walls.size()), 10, 100, 20, GREEN);
        
        // 处理输入
        handleInput();
    }
    
    void handleInput() {
        if (IsKeyPressed(KEY_R)) {
            showRays = !showRays;
        }
        if (IsKeyPressed(KEY_I)) {
            showIntersections = !showIntersections;
        }
        if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
            // 添加新墙壁
            static Vector2 lastClick = {0, 0};
            if (lastClick.x == 0 && lastClick.y == 0) {
                lastClick = curser;
            } else {
                walls.push_back({lastClick, curser});
                lastClick = {0, 0};
            }
        }
        if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) {
            // 清除所有墙壁（除了边界）
            if (walls.size() > 4) {
                walls.erase(walls.begin() + 4, walls.end());
            }
        }
    }

    // 生成射线方向
    void generateRayDirections(std::vector<Vector2>& directions, int count) {
        directions.clear();
        for (int i = 0; i < count; i++) {
            float angle = (float)i / count * 2 * PI;
            float distance = 2000.0f; // 足够长的射线
            Vector2 dir = {
                curser.x + cosf(angle) * distance,
                curser.y + sinf(angle) * distance
            };
            directions.push_back(dir);
        }
    }

    // 投射一条射线并返回最近的交点
std::optional<Vector2> castRay(const Vector2& rayStart, const Vector2& rayEnd) {
    std::optional<Vector2> closestIntersection;
    float closestDistance = std::numeric_limits<float>::max();
    
    // 收集所有墙壁端点
    std::vector<Vector2> wallEndpoints;
    for (auto& wall : walls) {
        wallEndpoints.push_back(wall.first);
        wallEndpoints.push_back(wall.second);
    }
    
    // 存储所有交点及其距离
    std::vector<std::pair<Vector2, float>> allIntersections;
    
    // 找到所有交点
    for (auto& wall : walls) {
        auto intersection = findRaySegmentIntersection(rayStart, rayEnd, wall.first, wall.second);
        if (intersection.has_value()) {
            float dist = vectorLength(Vector2{intersection->x - rayStart.x, intersection->y - rayStart.y});
            allIntersections.push_back({intersection.value(), dist});
        }
    }
    
    // 如果没有交点，返回空
    if (allIntersections.empty()) {
        return std::nullopt;
    }
    
    // 按距离排序所有交点
    std::sort(allIntersections.begin(), allIntersections.end(), 
              [](const auto& a, const auto& b) { return a.second < b.second; });
    
    // 寻找第一个不是端点的交点
    for (auto& [intersection, dist] : allIntersections) {
        bool isEndpoint = false;
        
        // 检查这个交点是否是墙壁端点
        for (auto& endpoint : wallEndpoints) {
            if (vectorLength(Vector2{intersection.x - endpoint.x, intersection.y - endpoint.y}) < 1e-6) {
                isEndpoint = true;
                break;
            }
        }
        
        // 如果不是端点，返回这个交点
        if (!isEndpoint) {
            return intersection;
        }
        
        // 如果是端点，检查这是否是第一个交点（最近的）
        // 如果是第一个交点，我们继续找下一个
        if (dist == allIntersections[0].second) {
            continue;
        }
    }
    
    // 如果所有交点都是端点，返回最近的端点
    return allIntersections[0].first;
}

    // 按角度对点进行排序（用于绘制视线多边形）
    std::vector<Vector2> sortPointsByAngle(std::vector<Vector2> points, const Vector2& center) {
        std::sort(points.begin(), points.end(), [&center](const Vector2& a, const Vector2& b) {
            float angleA = atan2f(a.y - center.y, a.x - center.x);
            float angleB = atan2f(b.y - center.y, b.x - center.x);
            return angleA < angleB;
        });
        return points;
    }

    // 计算叉积
    float crossProduct(const Vector2& a, const Vector2& b) {
        return a.x * b.y - a.y * b.x;
    }

    // 计算点积
    float dotProduct(const Vector2& a, const Vector2& b) {
        return a.x * b.x + a.y * b.y;
    }

    // 计算向量长度
    float vectorLength(const Vector2& v) {
        return std::sqrt(v.x * v.x + v.y * v.y);
    }

    // 检测射线与线段是否有交点
    bool simplcheck(
        const Vector2& rayStart,
        const Vector2& rayPoint,
        const Vector2& segStart,
        const Vector2& segEnd
    ) {
        Vector2 rayDir = {rayPoint.x - rayStart.x, rayPoint.y - rayStart.y};
        Vector2 segVec = {segEnd.x - segStart.x, segEnd.y - segStart.y};
        Vector2 startVec = {segStart.x - rayStart.x, segStart.y - rayStart.y};
        
        float cross = crossProduct(rayDir, segVec);
        
        if (std::abs(cross) < 1e-6) {
            return false;
        }
        
        float t = crossProduct(startVec, segVec) / cross;
        float u = crossProduct(startVec, rayDir) / cross;
        
        return (t >= 0) && (u >= 0) && (u <= 1);
    }

    // 检测射线与线段是否有交点并找出交点
    std::optional<Vector2> findRaySegmentIntersection(
        const Vector2& rayStart,
        const Vector2& rayPoint,
        const Vector2& segStart,
        const Vector2& segEnd
    ) {
        Vector2 rayDir = {rayPoint.x - rayStart.x, rayPoint.y - rayStart.y};
        Vector2 segVec = {segEnd.x - segStart.x, segEnd.y - segStart.y};
        Vector2 startVec = {segStart.x - rayStart.x, segStart.y - rayStart.y};
        
        float cross = crossProduct(rayDir, segVec);
        
        if (std::abs(cross) < 1e-6) {
            return std::nullopt;
        }
        
        float t = crossProduct(startVec, segVec) / cross;
        float u = crossProduct(startVec, rayDir) / cross;
        
        if (t >= 0 && u >= 0 && u <= 1) {
            Vector2 intersection = {
                rayStart.x + rayDir.x * t,
                rayStart.y + rayDir.y * t
            };
            return intersection;
        }
        
        return std::nullopt;
    }

    // 计算点到直线的距离
    float pointToLineDistance(
        const Vector2& point,
        const Vector2& linePoint1,
        const Vector2& linePoint2
    ) {
        Vector2 lineDir = {linePoint2.x - linePoint1.x, linePoint2.y - linePoint1.y};
        Vector2 pointVec = {point.x - linePoint1.x, point.y - linePoint1.y};
        
        float cross = std::abs(crossProduct(pointVec, lineDir));
        float lineLength = vectorLength(lineDir);
        
        if (lineLength < 1e-6) {
            Vector2 diff = {point.x - linePoint1.x, point.y - linePoint1.y};
            return vectorLength(diff);
        }
        
        return cross / lineLength;
    }
};